﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace DbJobsApi
{
    public static class QueryableExtender
    {
        /// <summary>
        /// 扩展排序
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="property">排序属性名</param>
        /// <param name="sord">排序asc或desc</param>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property, string sord)
        {
            string[] props = property.Split('.');
            Type type = typeof(T);
            ParameterExpression arg = Expression.Parameter(type, "x");
            Expression expr = arg;
            foreach (string prop in props)
            {
                PropertyInfo pi = type.GetProperty(prop);
                if (pi == null)
                {
                    throw new ArgumentNullException("不存在属性名" + prop);
                }
                expr = Expression.Property(expr, pi);
                type = pi.PropertyType;
            }
            Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
            LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

            string methodName = "OrderBy";
            if (sord.ToLower() != "asc")
                methodName = "OrderByDescending";

            object result = typeof(Queryable).GetMethods().Single(
                    method => method.Name == methodName
                            && method.IsGenericMethodDefinition
                            && method.GetGenericArguments().Length == 2
                            && method.GetParameters().Length == 2)
                    .MakeGenericMethod(typeof(T), type)
                    .Invoke(null, new object[] { source, lambda });
            return (IOrderedQueryable<T>)result;
        }
    }
}
